import store from '@/store'
import axios from 'axios'
import { Message } from 'element-ui'
import router from '@/router'

const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 20000 // 定义20秒超时
})

service.interceptors.request.use(
  config => {
    // 知识点:js文件中能否使用this.$store? 答案:不能 因为这是vue语法 js文件用不了
    // 解决方法:把store对象导入过来使用,是同一个store对象
    const token = store.getters.token
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)
// 响应拦截器
// 知识点1：axios内部的处理机制
// 1、http状态码为2xx，3xx就会给promise对象位置，返回成功的结果（resolve（））
// 2、http状态码为4xx,5xx就会给promise对象位置,返回错误的结果(reject())
// 如果想做一些操作,你可以在axios的相应拦截器自己来处理返回的结果
// 补充:http状态码有本次请求后,后端进行设置返回
// 响应拦截器
service.interceptors.response.use(
  response => {
    // http为2xx，3xx进入这里
    // 本项目成功/失败都是2xx响应状态码，都进入这里，所以需要自己根据字段判定
    // 知识点：axios内部会把后台返回数据直接放到data字段下面（第一个data是axios处理的）
    const { success, message } = response.data // 这个data是axios内部
    if (success) {
      return response.data // 直接返回后端数据, 省略一层data
    } else { // 成功
      // 返回response->返回的还是axios处理的结果对象（逻辑那边的.data.data）拿到后台返回值
      // 返回response.data->返回的就是后台返回的响应对象（逻辑那边拿到的真正的数据.data）拿到返回值
      // 特殊：返回到的是axios调用在原地留下的promise对象位置（逻辑页面await后面）
      Message.error(message) // http状态码2xx, 但是逻辑错误
      return Promise.reject(new Error(message)) // 返回Promise错误的对象
    }
  },
  error => {
    Message.error(error.response.data.message) // http状态码4xx
    // 判断错误状态码401
    // error.response && error.response.data && error.response.data.code === 10002
    //  前置非空判断(error有值才会执行&&后面的代码)
    // 确保error有值，在.response, .response有值，在.status
    // 防止null.xxxx,语法报错代码停止
    // 10000成功  10002 身份过期  10004xxxx
    if (error.response.data.code === 10002) {
      store.commit('REMOVE_TOKEN')
      store.commit('user/RESET_STATE')
      router.replace(`/login?path=${router.currentRoute.fullPath}`)
    }
    return Promise.reject(error)
  }
)

export default service
